# -*- coding: utf-8 -*-
"""
# 使用了 [joblib==1.4.2]，遵循其 [BSD] 许可证，原始代码来源：[https://joblib.readthedocs.io]
# 使用了 [matplotlib==3.7.4]，遵循其 [PSF] 许可证，原始代码来源：[https://matplotlib.org]
# 使用了 [pandas==2.0.3]，遵循其 [BSD 3-Clause License] 许可证，原始代码来源：[https://pandas.pydata.org]
# 使用了 [scikit-learn==1.3.2]，遵循其 [new BSD] 许可证，原始代码来源：[http://scikit-learn.org]
"""
import sys
from pathlib import Path
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import MiniBatchKMeans
import joblib

class PARA_CONFIG:
    CURRENT_DIR=Path(__file__).parent.resolve()
    TOPIC_PATH=CURRENT_DIR.parent.parent.resolve()/"02_lda"/"src"/"result"/"2_LDA_Topic_Allocation_01_SK_LDA_20251031_143518.xlsx"
#    TOPIC_PATH=CURRENT_DIR.parent.parent.resolve()/"02_lda"/"src"/"result"/"2_Gensim_Topics_02_GS_LDA_20251031_144009.xlsx"
    N_CLUSTER: int = 7
    FUNC_PATH=CURRENT_DIR.parent.parent.resolve()/"about_file"
sys.path.append(str(PARA_CONFIG.FUNC_PATH))
import f_basic

@f_basic.Timer
def do_kmeans(file_path: str,n_clusters: int = PARA_CONFIG.N_CLUSTER) -> str:
    df=pd.read_excel(file_path)
    X=StandardScaler().fit_transform(df.select_dtypes(include='number'))
    k_min = 2
    k_max = min(PARA_CONFIG.N_CLUSTER + 3, X.shape[0]//2)
    k_values = list(range(k_min, k_max + 1))
    def evaluate_k(k):
        mbk=MiniBatchKMeans(n_clusters=k,batch_size=1024,n_init=10,random_state=42)
        cluster_labels=mbk.fit_predict(X)
        sil_score=silhouette_score(X,cluster_labels)
        return k,mbk.inertia_,sil_score
    results=joblib.Parallel(n_jobs=-1)(joblib.delayed(evaluate_k)(k) for k in k_values)
    sorted_results=sorted(results, key=lambda x: x[0])
    k_sorted,inertias,sil_scores=zip(*sorted_results)
    fig,ax1=plt.subplots(figsize=(10,6))
    ax1.plot(k_sorted, inertias,'go-',linewidth=1.5,markersize=6,alpha=0.85,label='惯性值')
    ax2 = ax1.twinx()
    ax2.plot(k_sorted, sil_scores, 'ro-', linewidth=1.5, markersize=6, alpha=0.85, label='轮廓系数')
    ax2.set_ylim(min(sil_scores)-0.05, min(1, max(sil_scores)+0.05))
    ax1.set_yticklabels([])
    ax2.set_yticklabels([])
    ax1.grid(True, axis='both', linestyle='--', alpha=0.4)
    plt.grid(False)
    lines, labels = ax1.get_legend_handles_labels()
    lines2, labels2 = ax2.get_legend_handles_labels()
    plt.legend(lines+lines2,labels+labels2,loc='upper center',fontsize=12,frameon=True,fancybox=True,framealpha=0.8)
    f_basic.save_figure(fig,prefix="4_Silhouette")
    km=KMeans(n_clusters,n_init=1000,random_state=42)
    labels=km.fit_predict(X)
    df['label']=labels
    return(f_basic.save_dataframe(df,prefix="5_Kmeans"))
    
@f_basic.Timer 
def main_stream():
    """Kmeans start."""
    do_kmeans(PARA_CONFIG.TOPIC_PATH)

if __name__=="__main__":
    main_stream()
    